package org.nobject.common.file;

import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.nobject.common.lang.ClassUtils;
import org.nobject.common.lang.StringUtils;
import org.nobject.common.log.Log;

import sun.net.www.protocol.file.FileURLConnection;

/**
 * JarUtils
 *
 * @author benson
 * @date 2008-12-26
 */
public class JarUtils {
	
	/** 
	 * 获取JarFile
	 * @param path
	 */
	public static JarFile getJarFile(String path) {
		try {
			path=FileUtils.formatFilepath(path);
			if(!path.startsWith("/")){
				path="/"+path;
			}
			return ((JarURLConnection)new URL("jar:file:"+path+"!/").openConnection()).getJarFile();
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * getJarPath
	 * @param clazz
	 * @return
	 */
	public static String getJarPath(Class clazz){
		if(clazz==null) return null;
		String className=clazz.getName().replaceAll("\\.","/")+".class";
		return FileUtils.class.getClassLoader().getResource(className).toString();
	}
	
	/**
	 * getJarEntrys
	 * @param clazz
	 * @return
	 */
	public static List getJarEntrys(Class clazz){
		return getJarEntrys(clazz,null);
	}
	
	/**
	 * getJarEntrys
	 * @param clazz
	 * @param classpath
	 * @return
	 */
	public static List getJarEntrys(Class clazz,String classpath){
		return getJarEntrys(clazz.getName().replaceAll("\\.","/")+".class",classpath);
	}
	
	/**
	 * 获取Jar条目
	 * @param classpath 类路径
	 */
	public static List getJarEntrysByClasspath(String classpath){
		String packagepath 		=ClassUtils.getPackagepath(classpath);
		String classpathRegex	=ClassUtils.getClasspathRegex(ClassUtils.removePreClasspath(classpath));
		List jarEntrys=new LinkedList();
		try {
			//根据包找相关的所有Jar包
			Enumeration res=JarUtils.class.getClassLoader().getResources(packagepath);
			while(res.hasMoreElements()){
				URL resUrl=(URL) res.nextElement();
				Object o=resUrl.openConnection();
				if(o instanceof JarURLConnection||JarURLConnection.class.isAssignableFrom(o.getClass())){
					JarURLConnection con = (JarURLConnection) o;
					Enumeration e2=con.getJarFile().entries();
					//遍历Jar
					while(e2.hasMoreElements()){
						JarEntry jarEntry = (JarEntry) e2.nextElement();
						String sName=jarEntry.getName();
						if(sName.matches(classpathRegex)) jarEntrys.add(jarEntry);
					}
				}else{
					throw new RuntimeException("无法处理:"+resUrl.toURI());
				}
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return jarEntrys;
	}
	
	/**
	 * getJarEntrys
	 * @param resourName
	 */
	public static List getJarEntrys(String resourceName){
		return getJarEntrys(resourceName,null);
	}
	
	/**
	 * 获取资源所属的jar包
	 * 
	 * EXP:
	 * getJar(java.lang.String.class)
	 * 
	 * @param clazz 类
	 */
	public static JarFile getJar(Class clazz){
		return getJar(clazz.getName().replaceAll("\\.","/")+".class");
	}
	
	/**
	 * getJar<br>
	 * 获取资源所属的jar包
	 * @param resourceName
	 * @return
	 */
	public static JarFile getJar(String resourceName){
		try {
			Enumeration e=FileUtils.class.getClassLoader().getResources(resourceName);
			while(e.hasMoreElements()){
				URL jarFileUrl=(URL)e.nextElement();
				//jarFileUrl.openConnection().get
				System.out.println("JGP:"+jarFileUrl.getPath());
				URLConnection con=jarFileUrl.openConnection();
				if(!(con instanceof JarURLConnection)){
					//Log.warn("getJar faild :"+resourceName+":"+con.getClass().getName());
					continue;
				}else{
					return ((JarURLConnection)con).getJarFile();
				}
				
			}
		} catch (Exception e) {
			Log.error("getJar faild :"+e.getMessage());
			e.printStackTrace();
		}
		return null;
	}
	
	
	/** 
	 * getJar
	 * @param url
	 */
	public static JarFile getJar(URL url){
		URLConnection con;
		try {
			if(url.getProtocol().endsWith("file")){
				url=new URL("jar:"+url.toString()+"!/");
			}
			con = url.openConnection();
			return ((JarURLConnection)con).getJarFile();
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * getJarEntrys
	 * @param resourceName
	 * @param classpath
	 * @return
	 */
	public static List getJarEntrys(String resourceName,String classpath){
		List list=new LinkedList();
		try {
			classpath=ClassUtils.removePreClasspath(classpath);
			if(classpath==null) return list;
			classpath=classpath.replaceAll("\\.", "\\\\.").replaceAll("\\*", ".*");
			Enumeration e=FileUtils.class.getClassLoader().getResources(resourceName);
			while(e.hasMoreElements()){
				URL url=(URL)e.nextElement();
				JarURLConnection con = (JarURLConnection) url.openConnection();
				Enumeration e2=con.getJarFile().entries();
				while(e2.hasMoreElements()){
					JarEntry jarEntry = (JarEntry) e2.nextElement();
					if(StringUtils.isEmpty(classpath)||jarEntry.getName().matches(classpath)){
						list.add(jarEntry);
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return list;
	}
	
	
	public static void main(String[] args) throws Exception{
		
//		Enumeration e=XPathException.class.getClassLoader().getResources("/org/dom4j/XPathException.class");
//		if(e.hasMoreElements()){
//			URL jarFileUrl=(URL)e.nextElement();
//			System.out.println(jarFileUrl.getPath());
//			//jarFileUrl.openConnection().get
////			URLConnection con=jarFileUrl.openConnection();
////			sys
////			//JarURLConnection con = ;
////			if(!(con instanceof JarURLConnection)){
////				Log.warn("getJar faild :"+resourceName+":"+con.getClass().getName());
////				return null;
////			}
////			return ((JarURLConnection)con).getJarFile();
//		}
		
//		List l=getJarEntrysByClasspath("classpath:/org/nobject/common/lang/*.class");
//		System.err.println(l);
//		System.out.println(java.net.JarURLConnection.class.isAssignableFrom(sun.net.www.protocol.jar.JarURLConnection.class));
		
//		List list=getJarEntrysByClasspath("org/dom4j/*.class");
//		System.out.println(list.size());
//		for (Iterator iterator = list.iterator(); iterator.hasNext();) {
//			JarEntry jarEntry = (JarEntry) iterator.next();
//			System.out.println(jarEntry.getName());
//		}
//		JarFile jarFile=getJar(java.lang.String.class);
//		//Package p=new Package();
//		List lst=getJarEntrys(java.lang.String.class,"classpath:/java/lang/*.class");
//		for (Iterator iterator = lst.iterator(); iterator.hasNext();) {
//			JarEntry jarEntry = (JarEntry) iterator.next();
//			//InputStream is=jarFile.getInputStream(jarEntry);
//			System.out.println(jarEntry.getName());
////			System.out.println(is);
//		}
////		System.out.println("1");
//		
//		System.out.println(getJarPath(String.class));;
	}
}
